Refactor Xen Support for Intel Turbo Boost
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 9 Apr 2010 07:52:43 +0000 (08:52 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 9 Apr 2010 07:52:43 +0000 (08:52 +0100)
Refactor the existing code that supports the Intel Turbo feature to
move all the driver specific bits in the cpufreq driver.  Create
a tri-state interface for the Turbo feature that can distinguish
amongst enabled Turbo, disabled Turbo, and processors that don't
support Turbo at all.

Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com>
tools/libxc/xc_pm.c
tools/libxc/xenctrl.h
tools/misc/xenpm.c
xen/arch/x86/acpi/cpufreq/cpufreq.c
xen/drivers/acpi/pmstat.c
xen/drivers/cpufreq/cpufreq_ondemand.c
xen/drivers/cpufreq/utility.c
xen/include/acpi/cpufreq/cpufreq.h
xen/include/acpi/cpufreq/processor_perf.h
xen/include/public/sysctl.h

index 7d588346d568a8148dfb05b81017ebeac6f518f8..7e20231a33109e1a0cd3c70a1f37f1abe1be0fac 100644 (file)
@@ -247,6 +247,7 @@ int xc_get_cpufreq_para(int xc_handle, int cpuid,
         user_para->scaling_cur_freq = sys_para->scaling_cur_freq;
         user_para->scaling_max_freq = sys_para->scaling_max_freq;
         user_para->scaling_min_freq = sys_para->scaling_min_freq;
+        user_para->turbo_enabled    = sys_para->turbo_enabled;
 
         memcpy(user_para->scaling_driver, 
                 sys_para->scaling_driver, CPUFREQ_NAME_LEN);
index 9814d293dc389da5f2787c8962a54afabfda21a1..a12388db72f05857c356ec0905e707e16e61d196 100644 (file)
@@ -1292,6 +1292,8 @@ struct xc_get_cpufreq_para {
         xc_userspace_t userspace;
         xc_ondemand_t ondemand;
     } u;
+
+    int32_t turbo_enabled;
 };
 
 int xc_get_cpufreq_para(int xc_handle, int cpuid,
index b795adc9715ab4ac30df1225d755d84757327722..e1686592000d9d0e61e8540fbe44b874bd46cbf0 100644 (file)
 
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
 
+#define CPUFREQ_TURBO_DISABLED      -1
+#define CPUFREQ_TURBO_UNSUPPORTED   0
+#define CPUFREQ_TURBO_ENABLED       1
+
 static int xc_fd;
 static int max_cpu_nr;
 
@@ -62,8 +66,8 @@ void show_help(void)
             " set-max-cstate        <num>         set the C-State limitation (<num> >= 0)\n"
             " start [seconds]                     start collect Cx/Px statistics,\n"
             "                                     output after CTRL-C or SIGINT or several seconds.\n"
-            " enable-turbo-mode     [cpuid]       enable Turbo Mode in DBS governor.\n"
-            " disable-turbo-mode    [cpuid]       disable Turbo Mode in DBS governor.\n"
+            " enable-turbo-mode     [cpuid]       enable Turbo Mode for processors that support it.\n"
+            " disable-turbo-mode    [cpuid]       disable Turbo Mode for processors that support it.\n"
             );
 }
 /* wrapper function */
@@ -529,8 +533,6 @@ static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
                p_cpufreq->u.ondemand.sampling_rate);
         printf("    up_threshold     : %u\n",
                p_cpufreq->u.ondemand.up_threshold);
-        printf("    turbo mode       : %s\n",
-               p_cpufreq->u.ondemand.turbo_enabled ? "enabled" : "disabled");
     }
 
     printf("scaling_avail_freq   :");
@@ -546,6 +548,13 @@ static void print_cpufreq_para(int cpuid, struct xc_get_cpufreq_para *p_cpufreq)
            p_cpufreq->scaling_max_freq,
            p_cpufreq->scaling_min_freq,
            p_cpufreq->scaling_cur_freq);
+    if (p_cpufreq->turbo_enabled != CPUFREQ_TURBO_UNSUPPORTED) {
+           printf("turbo mode           : ");
+           if (p_cpufreq->turbo_enabled == CPUFREQ_TURBO_ENABLED)
+               printf("enabled\n");
+           else
+               printf("disabled\n");
+    }
     printf("\n");
 }
 
@@ -561,6 +570,7 @@ static int show_cpufreq_para_by_cpuid(int xc_fd, int cpuid)
     p_cpufreq->affected_cpus = NULL;
     p_cpufreq->scaling_available_frequencies = NULL;
     p_cpufreq->scaling_available_governors = NULL;
+    p_cpufreq->turbo_enabled = 0;
 
     do
     {
index 791cccd0d96d4bfdfaa00e381cc88fc187ea1d79..17776b47352bc2a6f99c2b786b2fdee9d96bc2f5 100644 (file)
@@ -410,6 +410,10 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
         return -ENODEV;
     }
 
+    if (policy->turbo == CPUFREQ_TURBO_DISABLED)
+        if (target_freq > policy->cpuinfo.second_max_freq)
+            target_freq = policy->cpuinfo.second_max_freq;
+
     perf = data->acpi_data;
     result = cpufreq_frequency_table_target(policy,
                                             data->freq_table,
@@ -610,12 +614,19 @@ acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
         break;
     }
 
-    /* Check for APERF/MPERF support in hardware */
+    /* Check for APERF/MPERF support in hardware
+     * also check for boost support */
     if (c->x86_vendor == X86_VENDOR_INTEL && c->cpuid_level >= 6) {
         unsigned int ecx;
+        unsigned int eax;
         ecx = cpuid_ecx(6);
         if (ecx & CPUID_6_ECX_APERFMPERF_CAPABILITY)
             acpi_cpufreq_driver.getavg = get_measured_perf;
+        eax = cpuid_eax(6);
+        if ( eax & 0x2 ) {
+            policy->turbo = CPUFREQ_TURBO_ENABLED;
+            printk(XENLOG_INFO "Turbo Mode detected and enabled!\n");
+        }
     }
 
     /*
index f1520004899714f6160f35482070e2224d2f0120..c88d000f63dd8e443d7cddc655b9015cd54e167e 100644 (file)
@@ -299,9 +299,8 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op)
             &op->u.get_para.u.ondemand.sampling_rate_min,
             &op->u.get_para.u.ondemand.sampling_rate,
             &op->u.get_para.u.ondemand.up_threshold);
-        op->u.get_para.u.ondemand.turbo_enabled =
-            cpufreq_dbs_get_turbo_status(op->cpuid);
     }
+    op->u.get_para.turbo_enabled = cpufreq_get_turbo_status(op->cpuid);
 
     return ret;
 }
@@ -553,13 +552,13 @@ int do_pm_op(struct xen_sysctl_pm_op *op)
 
     case XEN_SYSCTL_pm_op_enable_turbo:
     {
-        cpufreq_dbs_enable_turbo(op->cpuid);
+        cpufreq_enable_turbo(op->cpuid);
         break;
     }
 
     case XEN_SYSCTL_pm_op_disable_turbo:
     {
-        cpufreq_dbs_disable_turbo(op->cpuid);
+        cpufreq_disable_turbo(op->cpuid);
         break;
     }
 
index 5728a8fbaff7257a7cabb06d78bb01a1ad183e3e..dd4f6c45c17a5d7fbb44021b181c7397eb7ded9c 100644 (file)
@@ -58,9 +58,6 @@ static struct dbs_tuners {
 
 static struct timer dbs_timer[NR_CPUS];
 
-/* Turbo Mode */
-static int turbo_detected = 0;
-
 int write_ondemand_sampling_rate(unsigned int sampling_rate)
 {
     if ( (sampling_rate > MAX_SAMPLING_RATE / MICROSECS(1)) ||
@@ -111,10 +108,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 
     policy = this_dbs_info->cur_policy;
     max = policy->max;
-    if (turbo_detected && !this_dbs_info->turbo_enabled) {
-        if (max > policy->cpuinfo.second_max_freq)
-            max = policy->cpuinfo.second_max_freq;
-    }
 
     if (unlikely(policy->resume)) {
         __cpufreq_driver_target(policy, max,CPUFREQ_RELATION_H);
@@ -276,7 +269,6 @@ int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event)
             } else
                 dbs_tuners_ins.sampling_rate = usr_sampling_rate;
         }
-        this_dbs_info->turbo_enabled = 1;
         dbs_timer_init(this_dbs_info);
 
         break;
@@ -353,13 +345,6 @@ struct cpufreq_governor cpufreq_gov_dbs = {
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-#ifdef CONFIG_X86
-    unsigned int eax = cpuid_eax(6);
-    if ( eax & 0x2 ) {
-        turbo_detected = 1;
-        printk(XENLOG_INFO "Turbo Mode detected!\n");
-    }
-#endif
     return cpufreq_register_governor(&cpufreq_gov_dbs);
 }
 __initcall(cpufreq_gov_dbs_init);
@@ -404,19 +389,3 @@ void cpufreq_dbs_timer_resume(void)
         }
     }
 }
-
-void cpufreq_dbs_enable_turbo(int cpuid)
-{
-    per_cpu(cpu_dbs_info, cpuid).turbo_enabled = 1;
-}
-
-void cpufreq_dbs_disable_turbo(int cpuid)
-{
-    per_cpu(cpu_dbs_info, cpuid).turbo_enabled = 0;
-}
-
-unsigned int cpufreq_dbs_get_turbo_status(int cpuid)
-{
-    return turbo_detected && per_cpu(cpu_dbs_info, cpuid).turbo_enabled;
-}
-
index c730df951fc22523303dc6b5eebe3ead4aa03b89..612f7e0919251e4e9c8b406c48e5bdfe754080e6 100644 (file)
@@ -394,6 +394,31 @@ int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag)
     return policy->cur;
 }
 
+void cpufreq_enable_turbo(int cpuid)
+{
+    struct cpufreq_policy *policy;
+
+    policy = cpufreq_cpu_policy[cpuid];
+    if (policy->turbo != CPUFREQ_TURBO_UNSUPPORTED)
+        policy->turbo = CPUFREQ_TURBO_ENABLED;
+}
+
+void cpufreq_disable_turbo(int cpuid)
+{
+    struct cpufreq_policy *policy;
+
+    policy = cpufreq_cpu_policy[cpuid];
+    if (policy->turbo != CPUFREQ_TURBO_UNSUPPORTED)
+        policy->turbo = CPUFREQ_TURBO_DISABLED;
+}
+
+int cpufreq_get_turbo_status(int cpuid)
+{
+    struct cpufreq_policy *policy;
+
+    policy = cpufreq_cpu_policy[cpuid];
+    return policy->turbo;
+}
 
 /*********************************************************************
  *                 POLICY                                            *
index 4bdc74e0ac59d29564a2ced04193b2f5045aaec0..53c9a0d3148e42038ce5cd7eff2d576380ae744c 100644 (file)
@@ -55,6 +55,9 @@ struct cpufreq_policy {
 
     unsigned int        resume; /* flag for cpufreq 1st run
                                  * S3 wakeup, hotplug cpu, etc */
+    int                 turbo;  /* tristate flag: 0 for unsupported
+                                 * -1 for disable, 1 for enabled
+                                 * See CPUFREQ_TURBO_* below for defines */
 };
 extern struct cpufreq_policy *cpufreq_cpu_policy[NR_CPUS];
 
@@ -114,6 +117,14 @@ extern int __cpufreq_driver_target(struct cpufreq_policy *policy,
 #define USR_GETAVG     2
 extern int cpufreq_driver_getavg(unsigned int cpu, unsigned int flag);
 
+#define CPUFREQ_TURBO_DISABLED      -1
+#define CPUFREQ_TURBO_UNSUPPORTED   0
+#define CPUFREQ_TURBO_ENABLED       1
+
+extern void cpufreq_enable_turbo(int cpuid);
+extern void cpufreq_disable_turbo(int cpuid);
+extern int cpufreq_get_turbo_status(int cpuid);
+
 static __inline__ int 
 __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event)
 {
@@ -241,7 +252,4 @@ int write_userspace_scaling_setspeed(unsigned int cpu, unsigned int freq);
 void cpufreq_dbs_timer_suspend(void);
 void cpufreq_dbs_timer_resume(void);
 
-void cpufreq_dbs_enable_turbo(int cpuid);
-void cpufreq_dbs_disable_turbo(int cpuid);
-unsigned int cpufreq_dbs_get_turbo_status(int cpuid);
 #endif /* __XEN_CPUFREQ_PM_H__ */
index 72b55ead827e955a177c8c96f2e84804fdb6ac96..40b3a7103b62ceb9c3e93af39ced2b252bb25cff 100644 (file)
@@ -9,7 +9,6 @@
 int get_cpu_id(u8);
 int powernow_cpufreq_init(void);
 unsigned int powernow_register_driver(void);
-
 void cpufreq_residency_update(unsigned int, uint8_t);
 void cpufreq_statistic_update(unsigned int, uint8_t, uint8_t);
 int  cpufreq_statistic_init(unsigned int);
index eb9f1b8325fb3e4117eae12da02cae1071848c72..7255644286f1398c94416224c6a2372ea697c8e2 100644 (file)
@@ -283,7 +283,6 @@ struct xen_ondemand {
 
     uint32_t sampling_rate;
     uint32_t up_threshold;
-    uint32_t turbo_enabled;
 };
 typedef struct xen_ondemand xen_ondemand_t;
 
@@ -319,6 +318,8 @@ struct xen_get_cpufreq_para {
         struct  xen_userspace userspace;
         struct  xen_ondemand ondemand;
     } u;
+
+    int32_t turbo_enabled;
 };
 
 struct xen_set_cpufreq_gov {